#pragma once

#include "rewine/impl/CImage.hpp"

#include <map>
#include <memory>

namespace rewine
{

using dl_handle_t = void *;

class CDsoExport;

class CDsoImage : public CImage {
private:

    std::shared_ptr<dl_handle_t> m_Handle;
    int m_DynamicSymbolCount = 0;

    void *m_base = nullptr;
    const void *m_symtab = nullptr;
    const char *m_strtab = nullptr;

    using map_t = std::map<std::string, std::shared_ptr<CDsoExport>>;
    mutable map_t m_Cache;

public:

    CDsoImage() = default;
    ~CDsoImage() override = default;

private:

    int read_dynamic_symbol_count();

    CDsoExport *getCached(const std::string &name) const;
    CDsoExport *setCached(const std::string &name, void *value) const;

public:

    int init(const std::string &exportName, const std::string &fullname);
    int load();
    int unload();

public:

    ImageFlavour flavour() const override {
        return ImageFlavour::DSO;
    }

    int getExportCount() const override;
    IExport * getExportByIndex(unsigned int index) const override;
    IExport * getExportByName(const std::string& name, uint16_t hint) const override;

};

} // namespace rewine
